package com.caineng.zhaobiao.zbapi.controller;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.caineng.zhaobiao.zbapi.dao.CaiBaseUserDao;
import com.caineng.zhaobiao.zbapi.domain.CaiBaseUser;
import com.caineng.zhaobiao.zbapi.interceptor.logs.CainengApiLog;
import com.caineng.zhaobiao.zbapi.pay.wxapp.WxMaConfiguration;
import com.caineng.zhaobiao.zbapi.service.UserService;
import com.caineng.zhaobiao.zbapi.utils.AjaxResult;
import com.caineng.zhaobiao.zbapi.utils.RandomUserName;
import com.caineng.zhaobiao.zbapi.utils.ZhaoBiaoCommon;
import com.caineng.zhaobiao.zbapi.utils.cache.CacheUtils;
import com.caineng.zhaobiao.zbapi.utils.genID.IDUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Optional;

/**
 * 微信登录,支付等服务
 * @author liandyao
 * @date 2022/8/2 16:39
 */
@Api(tags = "微信登录接口")
@Slf4j
@RestController
@RequestMapping("/zbapi/wechat")
public class WechatController {

    @Autowired
    CaiBaseUserDao userDao;

    @Autowired
    UserService userService ;

    public final static String appid = "wx22d67ee49c77fd1b";


    /**
     * 微信小程序登录
     * @param code
     * @param rawData
     * @param signature
     * @param encryptedData
     * @param iv
     * @return
     */
    @CainengApiLog(title = "微信小程序登录")
    @ApiOperation(value = "第1步,获取用户昵称")
    @PostMapping("/miniAppLogin")
    public AjaxResult loginByWxapp(
            @RequestParam(value = "code", required = false) String code,
            @RequestParam(value = "rawData", required = false) String rawData,
            @RequestParam(value = "signature", required = false) String signature,
            @RequestParam(value = "encryptedData", required = false) String encryptedData,
            @RequestParam(value = "iv", required = false) String iv ) {
        if (StringUtils.isEmpty(code)) {
            return AjaxResult.error("empty code");
        }

        final WxMaService wxService = WxMaConfiguration.getMaService(appid);

        try {
            WxMaJscode2SessionResult sessionResult = wxService.getUserService().getSessionInfo(code);


            //session.setAttribute("sessionResult",sessionResult);
            //TODO 可以增加自己的逻辑，关联业务相关数据


            // 用户信息校验
            if (!wxService.getUserService().checkUserInfo(sessionResult.getSessionKey(), rawData, signature)) {
                return AjaxResult.error("用户信息校验失败!");
            }
            log.info(appid+"微信用户的unionId:"+sessionResult.getUnionid()+"   code:"+code);
            log.info(appid+"微信用户的openId:"+sessionResult.getOpenid()+"   code:"+code);

//            CaiBaseUser userParam = new CaiBaseUser();
//
//            userParam.setUnionid(sessionResult.getUnionid());
//            Optional<CaiBaseUser> userOpt = userDao.findOne(Example.of(userParam));

            CaiBaseUser user = userService.findUserByUnionid(sessionResult.getUnionid());

            // 解密 手机信息
            // WxMaPhoneNumberInfo phoneNoInfo = wxService.getUserService().getPhoneNoInfo(sessionResult.getSessionKey(), encryptedData, iv);
            // log.info("解密的手机号码是:"+ com.caineng.utils.StringUtils.toJson(phoneNoInfo));
            //使用缓存,将sessionResult放入缓存
            CacheUtils.put("sessionResult"+appid+sessionResult.getUnionid(),sessionResult);
            log.info("=========>"+appid+"============"+sessionResult.getUnionid()+"    "+CacheUtils.get("sessionResult"+appid+sessionResult.getUnionid()));


            if(user!=null){
                if(user.getDelFlag()== ZhaoBiaoCommon.delFlag_YES){
                    return AjaxResult.error(ZhaoBiaoCommon.DEL_FLAG_MSG);
                }
                /*if(StrUtil.isNotBlank(user.getPhone())) {
                    return userService.getAjaxResult(user);
                }else{
                    return AjaxResult.success("notPhone",sessionResult.getUnionid());
                }*/
                // 2024年12月26日 更改为 不需要绑定手机号码也可以登录
                return userService.getAjaxResult(user);
            }else{
                log.info("找不到微信用户");
                WxMaUserInfo wxUserInfo = wxService.getUserService().getUserInfo(sessionResult.getSessionKey(), encryptedData, iv);
                //如果没有就注册一个账号
                user = new CaiBaseUser();
                user.setId(IDUtils.getID());
                user.setOpenid(sessionResult.getOpenid());
                user.setUnionid(sessionResult.getUnionid());
                user.setShowName(wxUserInfo.getNickName());
                if(StrUtil.isBlank(wxUserInfo.getNickName()) || "微信用户".equals(wxUserInfo.getNickName())){
                    user.setShowName(RandomUserName.getUserName());
                }
                user.setHeadImg(wxUserInfo.getAvatarUrl());
                user.setCreateTime(DateUtil.now());
                userDao.insert(user);
                // 2024年12月26日 更改为 不需要绑定手机号码也可以登录
                return userService.getAjaxResult(user);
                //return AjaxResult.success("notPhone",sessionResult.getUnionid());
                //return AjaxResult.error("请点击微信快速登录",map);
            }
        } catch (WxErrorException e) {
            log.error(e.getMessage(), e);
            return AjaxResult.error("错误",e);
        }
    }

    /**
     * <pre>
     * 获取用户绑定手机号信息,微信小程序
     * </pre>
     */
    //@LogPrint
    @ApiOperation(value = "第2步,获取用户手机号码")
    @PostMapping("/wxAppPhone")
    @Transactional
    public AjaxResult wxAppPhone(String unionId,  String signature,
                              String rawData, String encryptedData, String iv) {
        log.info("=======sigature==="+signature+"  rowData==="+rawData+"  ====>  "+unionId);
        final WxMaService wxService = WxMaConfiguration.getMaService(appid);
        WxMaJscode2SessionResult sessionResult = (WxMaJscode2SessionResult) CacheUtils.get("sessionResult"+appid+unionId);

        if(sessionResult==null){
            return AjaxResult.error("登录失败,请重新进入小程序");
        }
        CacheUtils.remove("sessionResult"+appid); //用完就销毁

        String sessionKey =sessionResult.getSessionKey();
        log.info("电话号码校验:sessionKey:"+sessionKey+"  appid:"+appid);
        // 用户信息校验
        if (!wxService.getUserService().checkUserInfo(sessionKey, rawData, signature)) {
            return AjaxResult.error("user check failed");
        }
        // 用户非敏感信息：rawData
        JSONObject rawDataJson = JSONUtil.parseObj(rawData);
        // 解密
        WxMaPhoneNumberInfo phoneNoInfo = wxService.getUserService().getPhoneNoInfo(sessionKey, encryptedData, iv);
        log.info("解密的手机号码是:"+ JSONUtil.toJsonStr(phoneNoInfo));
        String phone = phoneNoInfo.getPhoneNumber();//获取到真正的手机号,与数据库进行对比

        String openid = sessionResult.getOpenid();

        CaiBaseUser userParam = new CaiBaseUser();
        userParam.setUnionid(sessionResult.getUnionid());
        Optional<CaiBaseUser> userOpt = userDao.findOne(Example.of(userParam));
        CaiBaseUser user = userOpt.orElse(null);
        if(user==null){
            return AjaxResult.error("当前用户不存在");
        }




        //查询是否之前用手机一键登录使用过，或者使用手机注册过
        CaiBaseUser userByPhone = userService.findUserByPhoneIgnoreDelFlag(phone);
        if(userByPhone==null){ //没有注册过，直接注册
            user.setPhone(phone);
            userDao.save(user);
            user.setPassword("");
            return userService.getAjaxResult(user);
        }else if(userByPhone.getDelFlag()==ZhaoBiaoCommon.delFlag_YES){
            return AjaxResult.error(ZhaoBiaoCommon.DEL_FLAG_MSG);
        }else{ //如果存在账号，且账号有效
            //覆盖原来的账号
            userByPhone.setUnionid(unionId);
            userByPhone.setOpenid(openid);
            userDao.save(userByPhone);
            //删除无效的user
            userDao.delete(user);
            return userService.getAjaxResult(userByPhone);
        }
    }

}
